package com.leo.base_project.module.socket;

import android.annotation.SuppressLint;
import android.os.Handler;
import android.os.Message;
import android.util.Log;

import com.leo.base_project.Utils.LogUtils;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/*
    需求分析
    需要生成一个Socket客户端
    具有接受信息和发送信息的功能
    在出现异常时抛出错误消息
    发送信息可以调用函数
    接受消息使用Handler传递消息
 */
public class SocketService {

    static String TAG = "MySocket";

    private Socket socket = null;
    String ip;
    int port;
    boolean receiving = false;

    private ExecutorService mExecutorService;
    // 用于接收对方发送的消息
    private ServerSocket dataServer;
    private BufferedReader reader;
    private PrintWriter printWriter;
    BufferedWriter writer;
    private String receiveMsg;

    Handler mHandler;

    public final static int CONNECTING = 1;
    public final static int CONNECTED = 2;
    public final static int CONNECT_ERR = 3;
    public final static int DISCONNECTED = 4;
    public final static int RECEIVED_MSG = 5;

    public final static String STOP_SIGNAL = "0";

    /*
     * 输入：IP地址，端口号
     * 创建时间: 2021/8/31 10:32
     * 创建者：Leo
     */
    public SocketService(Handler handler) {
        mExecutorService = Executors.newCachedThreadPool();
        mHandler = handler;
    }

    // ----------------------------- 实现方法 -----------------------------------

    public void connect(String ip, int port) {
        this.ip = ip;
        this.port = port;
        mHandler.sendEmptyMessage(CONNECTING);
        mExecutorService.execute(new connectService());  //在一个新的线程中请求 Socket 连接
    }

    public void send(String text) {
        mExecutorService.execute(new sendService(text));
    }

    public void disconnect() {
        mExecutorService.execute(new sendService(STOP_SIGNAL));
        try {
            // 关闭发送线程
            if (socket != null) {
                while (!socket.isClosed())
                    socket.close();
            }
            // 关闭接收线程
            if (dataServer != null) {
                while (!dataServer.isClosed())
                    dataServer.close();
            }
            // 关闭接收线程

            mHandler.sendEmptyMessage(DISCONNECTED);
        } catch (Exception e) {
            sendErrorMessage(e);
        }
    }

    // 获取数据
    public void startReceiving(int port) {
        mExecutorService.execute(new receiveService(port));
    }

    private void sendErrorMessage(Exception e) {
        if (mHandler != null) {
            sendCustomError(e.getMessage());
        }
    }

    private void sendCustomError(String s){
        if (mHandler != null) {
            Message msg = new Message();
            msg.what = CONNECT_ERR;
            msg.obj = s;
            mHandler.sendMessage(msg);
        }
    }

    /*
     * 类名：connectService
     * 功能：用于连接操作的线程
     * 创建时间: 2021/8/31 12:30
     * 创建者：Leo
     */
    private class connectService implements Runnable {

        @Override
        public void run() {
            try {
                socket = new Socket(ip, port);
                socket.setSoTimeout(60000);
                socket.getInputStream();
                writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), StandardCharsets.UTF_8));
                printWriter = new PrintWriter(writer, true);
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), StandardCharsets.UTF_8));
                mHandler.sendEmptyMessage(CONNECTED);
//                receiveMsg();
            } catch (Exception e) {
                sendErrorMessage(e);
                Log.e(TAG, ("connectService:" + e.getMessage()));   //如果Socket对象获取失败，即连接建立失败，会走到这段逻辑
            }
        }
    }

    private class sendService implements Runnable {
        private final String msg;

        sendService(String msg) {
            this.msg = msg;
        }

        @Override
        public void run() {
            if (writer == null) {
                sendCustomError("未建立连接");
            }
            try {
                writer.write(msg + "eof");
                writer.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
            if (msg.equals(STOP_SIGNAL)) {
                // 当我们自己发出停止指令后，还需要等待对方发来的停止指令才能停止
            }
        }
    }

    private class receiveService implements Runnable {
        int port;

        receiveService(int port) {
            this.port = port;
        }

        @Override
        public void run() {
            try {
                receiving = true;
                dataServer = new ServerSocket(port);
                while (receiving) {
                    //server尝试接收其他Socket的连接请求，server的accept方法是阻塞式的
                    Socket socket = dataServer.accept();
                    //每接收到一个Socket就建立一个新的线程来处理它
                    mExecutorService.execute(new mReceiveThread(socket));
                }
            } catch (Exception exception) {
                // 表示出现问题，可能是端口被占用了
                sendErrorMessage(exception);
                exception.printStackTrace();
                Log.e(TAG, "DataReceive: " + exception.getMessage());
            }
        }
    }

    private class mReceiveThread extends BaseThread {

        public mReceiveThread(Socket socket) throws IOException {
            super(socket);
        }

        @SuppressLint("SetTextI18n")
        @Override
        public void handleSocket() {
            while (receiving) {
                try {
                    // 获取接收到的所有数据
                    String str = getStrings();
                    LogUtils.d(TAG, "接收到：" + str);
                    if (str == null || str.equals(STOP_SIGNAL)) {
                        // 说明对面要停止了
                        // 1. 告诉对面我收到了，我也发个“0”
                        // 2. 停止当前服务
                        disconnect();
                        receiving = false;
                    } else {
                        Message msg = new Message();
                        msg.what = RECEIVED_MSG;
                        msg.obj = str;
                        mHandler.sendMessage(msg);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

        private String getStrings() throws IOException {
            char[] chars = new char[20];
            int len;
            StringBuilder sb = new StringBuilder();
            String substring = null;
            while ((len = mReader.read(chars)) != -1) {
                sb.append(new String(chars, 0, len));
                int eof = sb.toString().indexOf("eof");
                if (eof != -1) {
                    //判断结束标记
                    substring = sb.substring(0, sb.length() - 3);
                    break;
                }
            }
            return substring;
//            inputStream = mSocket.getInputStream();
//            bufferedInputStream = new BufferedInputStream(inputStream);
//            byte[] bytes = IOUtils.toByteArray(inputStream);
            // 获取字符串
        }
    }


}
